using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GameFramework.Event;
using Unity.VisualScripting;
using UnityGameFramework.Runtime;

namespace LS.UGFUnits
{
    [UnitCategory("Events/Unity Game Framework")]
    public abstract class FrameworkEventUnit<TArgs> : EventUnit<TArgs>, IFrameworkComponentUnit<EventComponent> where TArgs : GameFramework.Event.GameEventArgs
    {
        [DoNotSerialize]
        [PortLabelHidden]
        public ValueOutput Arg {get; protected set;}
        
        protected sealed override bool register => true;
        
        protected abstract int EventId { get; }
        
        protected abstract string HookName { get; }
        
        [DoNotSerialize]
        public EventComponent Target
        {
            get
            {
                if (FrameworkObserver.Observing())
                {
                    return FrameworkObserver.Event;
                }
                CheckFrameworkAvailable();
                return null;
            }
        }

        public override EventHook GetHook(GraphReference reference)
        {
            return new EventHook(HookName);
        }

        protected override void Definition()
        {
            base.Definition();
            Arg = ValueOutput<TArgs>(nameof(Arg));
        }

        public override void StartListening(GraphStack stack)
        {
            Target?.Subscribe(EventId, EventHandler);
            base.StartListening(stack);
        }

        public override void StopListening(GraphStack stack)
        {
            Target?.Unsubscribe(EventId, EventHandler);
            base.StopListening(stack);
        }

        protected override void AssignArguments(Flow flow, TArgs args)
        {
            flow.SetValue(Arg, args);
        }
        
        protected virtual void EventHandler(object sender, GameEventArgs args)
        {
            EventBus.Trigger(HookName, args);
        }
        
        public void CheckFrameworkAvailable()
        {
            if (!FrameworkObserver.GFAvailable)
            {
                Debug.LogError("Unity Game Framework is not available!");
            }
        }
    }
}
